package com.rla.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.rla.common.core.page.TableDataInfo;
import com.rla.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rla.common.utils.SecurityUtils;
import com.rla.common.utils.StringUtils;
import com.rla.service.IBaseHealthTargetRuleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.rla.domain.bo.EhsEverydayBloodFatBo;
import com.rla.domain.vo.EhsEverydayBloodFatVo;
import com.rla.domain.EhsEverydayBloodFat;
import com.rla.mapper.EhsEverydayBloodFatMapper;
import com.rla.service.IEhsEverydayBloodFatService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 日常记录-血脂记录Service业务层处理
 *
 * @author rla
 * @date 2025-09-11
 */
@RequiredArgsConstructor
@Service
public class EhsEverydayBloodFatServiceImpl implements IEhsEverydayBloodFatService {

    private final EhsEverydayBloodFatMapper baseMapper;

    private final IBaseHealthTargetRuleService iBaseHealthTargetRuleService;

    /**
     * 查询日常记录-血脂记录
     */
    @Override
    public EhsEverydayBloodFatVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询日常记录-血脂记录列表
     */
    @Override
    public TableDataInfo<EhsEverydayBloodFatVo> queryPageList(EhsEverydayBloodFatBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EhsEverydayBloodFat> lqw = buildQueryWrapper(bo);
        Page<EhsEverydayBloodFatVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询日常记录-血脂记录列表
     */
    @Override
    public List<EhsEverydayBloodFatVo> queryList(EhsEverydayBloodFatBo bo) {
        LambdaQueryWrapper<EhsEverydayBloodFat> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<EhsEverydayBloodFat> buildQueryWrapper(EhsEverydayBloodFatBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EhsEverydayBloodFat> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getUserId()), EhsEverydayBloodFat::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getMeasuredTime()), EhsEverydayBloodFat::getMeasuredTime, bo.getMeasuredTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTc()), EhsEverydayBloodFat::getTc, bo.getTc());
        lqw.eq(StringUtils.isNotBlank(bo.getTg()), EhsEverydayBloodFat::getTg, bo.getTg());
        lqw.eq(StringUtils.isNotBlank(bo.getHdl()), EhsEverydayBloodFat::getHdl, bo.getHdl());
        lqw.eq(StringUtils.isNotBlank(bo.getLdl()), EhsEverydayBloodFat::getLdl, bo.getLdl());
        lqw.eq(StringUtils.isNotBlank(bo.getSourceType()), EhsEverydayBloodFat::getSourceType, bo.getSourceType());
        lqw.like(StringUtils.isNotBlank(bo.getSourceName()), EhsEverydayBloodFat::getSourceName, bo.getSourceName());
        lqw.eq(StringUtils.isNotBlank(bo.getIsLook()), EhsEverydayBloodFat::getIsLook, bo.getIsLook());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceCode()), EhsEverydayBloodFat::getDeviceCode, bo.getDeviceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getBusinessId()), EhsEverydayBloodFat::getBusinessId, bo.getBusinessId());
//        lqw.eq(StringUtils.isNotBlank(bo.getTag()), EhsEverydayBloodFat::getTag, bo.getTag());
        lqw.eq(StringUtils.isNotBlank(bo.getColor()), EhsEverydayBloodFat::getColor, bo.getColor());
        lqw.eq(bo.getFgcCreatedate() != null, EhsEverydayBloodFat::getFgcCreatedate, bo.getFgcCreatedate());
        lqw.eq(StringUtils.isNotBlank(bo.getFgcLastmodifier()), EhsEverydayBloodFat::getFgcLastmodifier, bo.getFgcLastmodifier());
        lqw.eq(bo.getFgcLastmodifydate() != null, EhsEverydayBloodFat::getFgcLastmodifydate, bo.getFgcLastmodifydate());
        lqw.eq(StringUtils.isNotBlank(bo.getFgcCreator()), EhsEverydayBloodFat::getFgcCreator, bo.getFgcCreator());
        if (StringUtils.isNotBlank(bo.getTag()) && "正常".equals(bo.getTag())) {
            lqw.eq(StringUtils.isNotBlank(bo.getTag()), EhsEverydayBloodFat::getTag, bo.getTag());
        } else if (StringUtils.isNotBlank(bo.getTag()) && "异常".equals(bo.getTag())) {
            lqw.and(StringUtils.isNotBlank(bo.getTag()) && "异常".equals(bo.getTag()), w -> {
                w.eq(EhsEverydayBloodFat::getTag, "边缘升高").or().eq(EhsEverydayBloodFat::getTag, "高血脂");
            });
        }
        lqw.orderByDesc(EhsEverydayBloodFat::getMeasuredTime);
        return lqw;
    }

    /**
     * 新增日常记录-血脂记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insertByBo(EhsEverydayBloodFatBo bo) {
        bo.setUserId(SecurityUtils.getUserId().toString());
        EhsEverydayBloodFat add = BeanUtil.toBean(bo, EhsEverydayBloodFat.class);
        validEntityBeforeSave(add);
        add.setCreateBy(SecurityUtils.getUserId().toString());
        add.setCreateTime(new Date());

        String tcResultTag = "";
        String tgResultTag = "";
        String hdlResultTag = "";
        String ldlResultTag = "";
        String tcResultTagColor = "";
        String tgResultTagColor = "";
        String hdlResultTagColor = "";
        String ldlResultTagColor = "";
        // ---------------------- 总胆固醇（TC）处理 ----------------------
        if (StringUtils.isNotBlank(bo.getTc())) {
            Map<String, Object> tcResult = iBaseHealthTargetRuleService.calculateIndicators(
                    "血脂",
                    "64",
//                    bo.getMeasuredType(),
                    Double.valueOf(bo.getTc())
            );
            tcResultTag = tcResult.get("tag").toString();
            tcResultTagColor = tcResult.get("color").toString();
        }

        // ---------------------- 甘油三酯（TG）处理 ----------------------
        if (StringUtils.isNotBlank(bo.getTg())) {
            Map<String, Object> tgResult = iBaseHealthTargetRuleService.calculateIndicators(
                    "血脂",
                    "65",
//                    bo.getMeasuredType(),
                    Double.valueOf(bo.getTg())
            );
            tgResultTag = tgResult.get("tag").toString();
            tgResultTagColor = tgResult.get("color").toString();
        }

        // ---------------------- 高密度脂蛋白胆固醇（HDL - C）处理 ----------------------
        if (StringUtils.isNotBlank(bo.getHdl())) {
            Map<String, Object> hdlResult = iBaseHealthTargetRuleService.calculateIndicators(
                    "血脂",
                    "67",
//                    bo.getMeasuredType(),
                    Double.valueOf(bo.getHdl())
            );
            hdlResultTag = hdlResult.get("tag").toString();
            hdlResultTagColor = hdlResult.get("color").toString();
        }

        // ---------------------- 低密度脂蛋白胆固醇（LDL - C）处理 ----------------------
        if (StringUtils.isNotBlank(bo.getLdl())) {
            Map<String, Object> ldlResult = iBaseHealthTargetRuleService.calculateIndicators(
                    "血脂",
                    "66",
//                    bo.getMeasuredType(),
                    Double.valueOf(bo.getLdl())
            );
            ldlResultTag = ldlResult.get("tag").toString();
            ldlResultTagColor = ldlResult.get("color").toString();
        }

        if (ObjectUtil.isNotEmpty(tcResultTag) && "正常".equals(tgResultTag) && "正常".equals(hdlResultTag) && "正常".equals(ldlResultTag)) {
            add.setTag(tcResultTag);
            add.setColor(tcResultTagColor);
        } else {
            if (!"正常".equals(tcResultTag)) {
                add.setTag(tcResultTag);
                add.setColor(tcResultTagColor);
            } else if (!"正常".equals(tgResultTag)) {
                add.setTag(tgResultTag);
                add.setColor(tgResultTagColor);
            } else if (!"正常".equals(hdlResultTag)) {
                add.setTag(hdlResultTag);
                add.setColor(hdlResultTagColor);
            } else if (!"正常".equals(ldlResultTag)) {
                add.setTag(ldlResultTag);
                add.setColor(ldlResultTagColor);
            }
        }
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return add.getId();
    }

    /**
     * 修改日常记录-血脂记录
     */
    @Override
    public Boolean updateByBo(EhsEverydayBloodFatBo bo) {
        EhsEverydayBloodFat update = BeanUtil.toBean(bo, EhsEverydayBloodFat.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(EhsEverydayBloodFat entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除日常记录-血脂记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    // 常量定义
    private static final String NO_DATA_FLAG = "-";
    private static final String INCREASE_FLAG = "1";
    private static final String DECREASE_FLAG = "0";
    private static final int TEN_DAYS_OFFSET = -10;

    /**
     * 设置默认值
     */
    private void setDefaultValues(Map<String, Object> result, String prefix) {
        result.put(prefix + "TgFlag", DECREASE_FLAG);
        result.put(prefix + "TcFlag", DECREASE_FLAG);
        result.put(prefix + "HdlFlag", DECREASE_FLAG);
        result.put(prefix + "LdlFlag", DECREASE_FLAG);
        result.put(prefix + "TgDiff", NO_DATA_FLAG);
        result.put(prefix + "TcDiff", NO_DATA_FLAG);
        result.put(prefix + "HdlDiff", NO_DATA_FLAG);
        result.put(prefix + "LdlDiff", NO_DATA_FLAG);
        result.put(prefix + "Date", NO_DATA_FLAG);

        if ("tenDays".equals(prefix)) {
            result.put("betweenDay", NO_DATA_FLAG);
        }
    }

    @Override
    public Map<String, Object> queryDateCompare(String id) {
        // 参数校验
        if (StringUtils.isBlank(id)) {
            throw new IllegalArgumentException("血脂记录ID不能为空");
        }

        // 获取当前血压记录
        EhsEverydayBloodFatVo fatRecord = baseMapper.selectVoById(id);
        if (fatRecord == null) {
            throw new IllegalArgumentException("未找到指定的血压记录");
        }

        String measuredTime = fatRecord.getMeasuredTime();
        String tg = fatRecord.getTg();
        String tc = fatRecord.getTc();
        String hdl = fatRecord.getHdl();
        String ldl = fatRecord.getLdl();

        Map<String, Object> result = new HashMap<>();

        // 处理最近一次记录比较
        processLastRecordComparison(measuredTime, tg, tc,hdl,ldl, result);

        // 处理近10天记录比较
        processTenDaysComparison(measuredTime, tg, tc,hdl,ldl, result);

        return result;
    }

    @Override
    public Map<String, Object> statisticsExce(EhsEverydayBloodFatBo bo) {
        //正常异常数量统计
        String startDate = bo.getStartDate()+" 00:00:00";
        String endDate = bo.getEndDate()+" 23:59:59";
        List<Map<String, Object>> maps = baseMapper.statisticsExce(bo.getUserId(), startDate, endDate);
        Map<String, Object> map1 = new HashMap<>();
        if(ObjectUtil.isNotEmpty(maps)){
            for (Map<String, Object> map : maps) {
                map1.put(map.get("tag").toString(), map.get("num").toString());
            }
        }
        return map1;
    }

    @Override
    public List<Map<String, Object>> queryTrendList(EhsEverydayBloodFatBo bo) {
        List<Map<String, Object>> list = new ArrayList<>();
//        DateUtil
        String startDate = bo.getStartDate()+" 00:00:00";
        String endDate = bo.getEndDate()+" 23:59:59";

        //趋势数据图表
        list = baseMapper.getTrendList(bo.getUserId(),startDate,endDate);

        return list;
    }

    @Override
    public Map<String, Object> healthReport(EhsEverydayBloodFatBo bo) {
        String startDate = bo.getStartDate()+" 00:00:00";
        String endDate = bo.getEndDate()+" 23:59:59";
        Map<String, Object> healthReportCountMap = baseMapper.healthReport(bo.getUserId(), startDate, endDate);
        Map<String, Object> map1 = new HashMap<>();

        List<Map<String, Object>> maps = baseMapper.getTagCountStatistics(bo.getUserId(), startDate, endDate);
        if(ObjectUtil.isNotEmpty(maps)){
            for (Map<String, Object> map : maps) {
                map1.put(map.get("tagName").toString(), map.get("tagCount").toString());
            }
        }
        map1.put("count",ObjectUtil.isNotEmpty(healthReportCountMap.get("num"))? healthReportCountMap.get("num"):0 );
        map1.put("avgTcValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("avgTcValue"))? healthReportCountMap.get("avgTcValue"):0 );
        map1.put("avgTgValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("avgTgValue"))? healthReportCountMap.get("avgTgValue"):0 );
        map1.put("avgHdlValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("avgHdlValue"))? healthReportCountMap.get("avgHdlValue"):0 );
        map1.put("avgLdlValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("avgLdlValue"))? healthReportCountMap.get("avgLdlValue"):0 );
        return map1;
    }

    private void processLastRecordComparison(String measuredTime, String tgParam,
                                             String tcParam, String hdlParam, String ldlParam, Map<String, Object> result) {
        Map<String, Object> lastRecord = baseMapper.queryDateCompare(measuredTime);

        if (ObjectUtil.isEmpty(lastRecord)) {
            setDefaultValues(result, "last");
            return;
        }

        String lastTgParam = lastRecord.get("tc").toString();
        String lastTcParam = lastRecord.get("tg").toString();
        String lastHdlParam = lastRecord.get("hdl").toString();
        String lastLdlParam = lastRecord.get("ldl").toString();
        String lastDate = lastRecord.get("measuredTimeFormat").toString();

        // 计算血压差值
        BloodPressureDiff tgDiff = calculateBloodPressureDiff(tgParam, lastTgParam);
        BloodPressureDiff tcDiff = calculateBloodPressureDiff(tcParam, lastTcParam);
        BloodPressureDiff hdlDiff = calculateBloodPressureDiff(hdlParam, lastHdlParam);
        BloodPressureDiff ldlDiff = calculateBloodPressureDiff(ldlParam, lastLdlParam);

        // 设置结果
        result.put("lastTgDiff", tgDiff.diff);
        result.put("lastTcDiff", tcDiff.diff);
        result.put("lastHdlDiff", hdlDiff.diff);
        result.put("lastLdlDiff", ldlDiff.diff);
        result.put("lastDate", lastDate);
        result.put("lastTgFlag", tgDiff.flag);
        result.put("lastTcFlag", tcDiff.flag);
        result.put("lastHdlFlag", hdlDiff.diff);
        result.put("lastLdlFlag", ldlDiff.diff);
    }

    /**
     * 处理近10天记录比较
     */
    private void processTenDaysComparison(String measuredTime, String tgParam,
                                          String tcParam, String hdlParam, String ldlParam, Map<String, Object> result) {
        try {
            DateTime currentDate = DateUtil.parse(measuredTime);
            String tenDaysAgo = DateUtil.offsetDay(currentDate, TEN_DAYS_OFFSET).toDateStr();
            Map<String, Object> tenDaysRecord = baseMapper.queryDateCompare(tenDaysAgo);

            if (ObjectUtil.isEmpty(tenDaysRecord)) {
                setDefaultValues(result, "tenDays");
                return;
            }

            String tenDaysTc = tenDaysRecord.get("tc").toString();
            String tenDaysTg = tenDaysRecord.get("tg").toString();
            String tenDaysHdl = tenDaysRecord.get("hdl").toString();
            String tenDaysLdl = tenDaysRecord.get("ldl").toString();
            String tenDaysDate = tenDaysRecord.get("measuredTimeFormat").toString();

            // 计算血压差值
            BloodPressureDiff tgDiff = calculateBloodPressureDiff(tgParam, tenDaysTc);
            BloodPressureDiff tcDiff = calculateBloodPressureDiff(tcParam, tenDaysTg);
            BloodPressureDiff hdlDiff = calculateBloodPressureDiff(hdlParam, tenDaysHdl);
            BloodPressureDiff ldlDiff = calculateBloodPressureDiff(ldlParam, tenDaysLdl);

            // 计算天数差
            long betweenDays = calculateDaysBetween(measuredTime, tenDaysRecord.get("measuredTime").toString());

            // 设置结果
            result.put("tenDaysTgDiff", tgDiff.diff);
            result.put("tenDaysTcDiff", tcDiff.diff);
            result.put("tenDaysHdlDiff", hdlDiff.diff);
            result.put("tenDaysLdlDiff", ldlDiff.diff);
            result.put("tenDaysDate", tenDaysDate);
            result.put("betweenDay", betweenDays);
            result.put("tenDaysTgFlag", tgDiff.flag);
            result.put("tenDaysTcFlag", tcDiff.flag);
            result.put("tenDaysHdlFlag", hdlDiff.flag);
            result.put("tenDaysLdlFlag", ldlDiff.flag);

        } catch (Exception e) {
            // 日期解析异常时设置默认值
            setDefaultValues(result, "tenDays");
        }
    }

    /**
     * 计算两个日期之间的天数差
     */
    private long calculateDaysBetween(String dateStr1, String dateStr2) {
        try {
            Date date1 = DateUtil.parse(dateStr1);
            Date date2 = DateUtil.parse(dateStr2);
            return DateUtil.between(date1, date2, DateUnit.DAY);
        } catch (Exception e) {
            return 0;
        }
    }

    private static class BloodPressureDiff {
        final BigDecimal diff;
        final String flag;

        BloodPressureDiff(BigDecimal diff, String flag) {
            this.diff = diff;
            this.flag = flag;
        }
    }

    private BloodPressureDiff calculateBloodPressureDiff(String currentPressure, String comparePressure) {
        try {
            BigDecimal current = new BigDecimal(currentPressure);
            BigDecimal compare = new BigDecimal(comparePressure);
            BigDecimal diff = current.subtract(compare);
            String flag = diff.compareTo(BigDecimal.ZERO) > 0 ? INCREASE_FLAG : DECREASE_FLAG;
            return new BloodPressureDiff(diff, flag);
        } catch (NumberFormatException e) {
            return new BloodPressureDiff(new BigDecimal(0), DECREASE_FLAG);
        }
    }
}
